package br.pucrio.inf.cmm.wrappers;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import br.pucrio.inf.csm.Attribute;
import br.pucrio.inf.csm.CatalogAccessException;
import br.pucrio.inf.csm.ICatalogWrapper;
import br.pucrio.inf.csm.ISchema;
import br.pucrio.inf.csm.Instance;
import br.pucrio.inf.csm.caching.Cache;
import br.pucrio.inf.csm.caching.CacheManager;
import br.pucrio.inf.csm.caching.CachePolicyOption;

/**
 * A Proxy for catalog wrapper.
 * 
 * @author agazola
 * 
 */
public class CatalogWrapperCacheProxy implements ICatalogWrapper {

	private final ICatalogWrapper catalogWrapper;

//	private ILocalPersistenceService persistence;

	private CacheManager cacheManager;

	private static final Object NullKey = new Object();

	private static final String CACHE_FOR_GET_INSTANCE_ATTRIBUTE_VALUES = "getInstanceAttributeValues";

	private static final String CACHE_FOR_GET_INSTANCE_BY_THESAURUS_TERM = "getInstanceByThesaurusTerm";

	private static final String CACHE_FOR_GET_SIMILARITY_COUNT = "getSimilarityCount";
	
	public CatalogWrapperCacheProxy(ICatalogWrapper catalogWrapper,
			CachePolicyOption cachePolicy/*, ILocalPersistenceService persistence*/) {
		this.catalogWrapper = catalogWrapper;
		//this.persistence = persistence;

		// TODO: colocar este parametro no conf
		final int defaultCacheSize = 10000;

		cacheManager = CacheManager.getInstance();
		cacheManager.createCache(CACHE_FOR_GET_INSTANCE_ATTRIBUTE_VALUES,
				cachePolicy, defaultCacheSize);
		cacheManager.createCache(CACHE_FOR_GET_INSTANCE_BY_THESAURUS_TERM,
				cachePolicy, defaultCacheSize);
		cacheManager.createCache(CACHE_FOR_GET_SIMILARITY_COUNT, cachePolicy,
				defaultCacheSize);
	}

	@Override
	public List<String> getInstanceAttributeValues(Attribute schemaAttr,
			ISchema schema) throws CatalogAccessException {
		return catalogWrapper.getInstanceAttributeValues(schemaAttr, schema);
	}

	@Override
	public List<Instance> getInstancesByThesaurusTerm(String term,
			ISchema schema) {
		List<Instance> instances = persistence
				.getInstancesInLocalDBByThesaurusTerm(term, schema);
		if (instances == null || instances.isEmpty()) {
			instances = catalogWrapper
					.getInstancesByThesaurusTerm(term, schema);
			try {
				persistence.saveInstances(instances);
			} catch (PersistenceException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return instances;
	}

	@Override
	public int getSimilarityCount(ISchema schema, Attribute schemaAttr,
			String value) throws CatalogAccessException {
		Cache cache = cacheManager.getCache(CACHE_FOR_GET_SIMILARITY_COUNT);
		Object key = generateArgumentKey(schema, schemaAttr, value);
		Object obj = cache.retrieve(key);
		if (obj != null && obj instanceof Integer) {
			return (Integer) obj;
		} else {
			int count = catalogWrapper.getSimilarityCount(schema, schemaAttr,
					value);
			cache.store(key, count);
			return count;
		}
	}

	@Override
	public List<String> getThesaurus(ISchema schema)
			throws CatalogAccessException {
		List<String> thesaurus = new ArrayList<String>();
		/*try {
			thesaurus = persistence.getThesaurus(schema.getName());
		} catch (PersistenceException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if (thesaurus == null || thesaurus.isEmpty()) {
			thesaurus = catalogWrapper.getThesaurus(schema);
		}*/
		return thesaurus;
	}

	private Object generateArgumentKey(Object... args) {
		return args != null ? Arrays.asList(args) : NullKey;
	}

}
